<?php

namespace App\Console\Server;

use App\Console\Base;
use Illuminate\Console\Scheduling\Schedule;
use Swoole\Process;

class CommandDispatch extends Base
{
    /**
     * 控制台命令 signature 的名称。
     *
     * @var string
     */
    protected $signature = 'uniform:command_dispatch';

    /**
     * 控制台命令说明。
     *
     * @var string
     */
    protected $description = '定时任务分发服务，整个环境只能运行一个！';

    /**
     * The schedule instance.
     *
     * @var \Illuminate\Console\Scheduling\Schedule
     */
    public $schedule;

    /**
     * cron定时器
     * 
     * @var int
     */
    public $cronTimer;

    /**
     * Create a new command instance.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    public function __construct(Schedule $schedule)
    {
        $this->schedule = $schedule;
        parent::__construct();
    }

    /**
     * 执行控制台命令。
     *
     * @return mixed
     */
    public function handle()
    {
        $process = new Process(function(Process $worker){
            swoole_set_process_name("uniform:command_dispatch");
            $this->startTick();
            $this->startCron();
        });
        $process->start();
        Process::wait();
    }

    /**
     * 启动Tick循环任务
     */
    public function startTick()
    {
        $events = $this->schedule->getTickEvents();
        foreach ($events as $e) {
            $this->starTimer($e);
        }
    }

    /**
     * 自管理Tick任务
     */
    public function starTimer(Event $e)
    {
        $t = $e->getIntervalTime();
        if ($t <= 0) {
            return;
        }

        swoole_timer_after($t * 1000, function () use ($e) {
            $e->dispatch();
            $this->starTimer($e);
        });
    }

    /**
     * crontab
     */
    public function startCron()
    {
        if ($this->cronTimer) {
            return;
        }
        // 整分运行任务
        $s = date('s');
        if ($s == '00') {
            $this->info("Start crontab:");
            $this->checkSchedule();
            $this->cronTimer = swoole_timer_tick(60 * 1000, [$this, 'checkSchedule']);
        } else {
            swoole_timer_after(1000, [$this, 'startCron']);
        }
    }

    /**
     * 常规cron任务
     */
    public function checkSchedule()
    {
        $events = $this->schedule->getSchedule();
        while (count($events) > 0) {
            $e = array_shift($events);
            $e->dispatch();
        }
    }
}
